package com.wmx.thread.future.completablefuture;

import lombok.extern.slf4j.Slf4j;

import java.util.concurrent.*;

/**********************************
 * @author wmx
 * @date 2019/9/26 9:12
 * @description:
 * @version 1.0
 *
 *
 * 一、方法说明
1、shutdown()：停止接收新任务，原来的任务继续执行
英文原意：关闭，倒闭;停工。 这里的意思是 关闭线程池。与使用数据库连接池一样，每次使用完毕后，都要关闭线程池。

1、停止接收新的submit的任务；
2、已经提交的任务（包括正在跑的和队列中等待的）,会继续执行完成；
3、等到第2步完成后，才真正停止；

2、shutdownNow()：停止接收新任务，原来的任务停止执行
1、跟 shutdown() 一样，先停止接收新submit的任务；

2、忽略队列里等待的任务；

3、尝试将正在执行的任务interrupt中断；

4、返回未执行的任务列表；

说明：它试图终止线程的方法是通过调用 Thread.interrupt() 方法来实现的，这种方法的作用有限，如果线程中没有sleep 、wait、Condition、定时锁等应用, interrupt() 方法是无法中断当前的线程的。所以，shutdownNow() 并不代表线程池就一定立即就能退出，它也可能必须要等待所有正在执行的任务都执行完成了才能退出。但是大多数时候是能立即退出的。

3、awaitTermination(long timeOut, TimeUnit unit)：当前线程阻塞
timeout 和 TimeUnit 两个参数，用于设定超时的时间及单位

当前线程阻塞，直到：

等所有已提交的任务（包括正在跑的和队列中等待的）执行完；
或者 等超时时间到了（timeout 和 TimeUnit设定的时间）；
或者 线程被中断，抛出InterruptedException
然后会监测 ExecutorService 是否已经关闭，返回true（shutdown请求后所有任务执行完毕）或false（已超时）

二、区别
1、shutdown() 和 shutdownNow() 的区别
shutdown() 只是关闭了提交通道，用submit()是无效的；而内部该怎么跑还是怎么跑，跑完再停。
shutdownNow() 能立即停止线程池，正在跑的和正在等待的任务都停下了。

2、shutdown() 和 awaitTermination() 的区别
shutdown() 后，不能再提交新的任务进去；但是 awaitTermination() 后，可以继续提交。

awaitTermination()是阻塞的，返回结果是线程池是否已停止（true/false）；shutdown() 不阻塞。

三、总结
1、优雅的关闭，用 shutdown()

2、想立马关闭，并得到未执行任务列表，用shutdownNow()

3、优雅的关闭，并允许关闭声明后新任务能提交，用 awaitTermination()

4、关闭功能 【从强到弱】 依次是：shuntdownNow() > shutdown() > awaitTermination()
 *
 *
 *
 ************************************/
@Slf4j
public class CompletableFutureDemo {



    //疑问：异步调用时 ，主线程停止后，异步调用就失败吗
    public static void main(String[] args) {

        ExecutorService executorService = Executors.newFixedThreadPool(10);

         Future<?> fure = executorService.submit(new Task());



        log.info("调用主线程");
        executorService.shutdown();

        /*long start = System.currentTimeMillis();
        for (int i = 0; i < 1000; i++) {
            int a = i;
            CompletableFuture.supplyAsync(() -> {
                log.info("======================当前线程=====================" + Thread.currentThread().getName());
                try {
                    TimeUnit.SECONDS.sleep((int) (Math.random() * 5));
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                return a;
            }, executorService).thenAccept((b) -> {
                log.info("" + b);
            });
        }

        System.out.println("主线程=============================");
        executorService.shutdown();*/
        //executorService.shutdownNow();

    }

    static class Task implements Callable<Integer>{

        @Override
        public Integer call() throws Exception {

            return 3;
        }
    }

}
